<template>
  <div class="op-group comp-op-filter">
    <div class="op-title">筛选</div>
    <template v-for="(optionConfig, index) in optionSetting">
      <div
        v-if="
          optionConfig.showFunc(
            selectionInfo,
            columnHasNullCell,
            isNumberCell,
            maxMinOptions,
            optionConfig.selectionType
          )
        "
        :key="optionConfig.selectionType"
        class="option-item"
      >
        <div class="title-row">
          <span class="label">
            <span
              class="view-icon"
              title="预览"
              @mouseleave="onMouseLeave()"
              @mouseenter="onMouseEnter($event, optionConfig.selectionType)"
            >
              <img src="~@/assets/dataset/preview.png" alt="preview" />
            </span>
            <template v-if="isGTLT(optionConfig.selectionType)">
              <compare-filter
                v-if="!optionConfig.isShowSub"
                v-model="bindData.compare"
                :max="maxMinOptions[1]"
                :min="maxMinOptions[0]"
                :default-delimiter="maxMinOptions[1]"
                :default-compare-mode="'='"
              >
              </compare-filter>
              <span v-else
                >已选出“{{ bindData.compare.compareMode
                }}{{ bindData.compare.delimiter }}”的单元格</span
              >
            </template>
            <template v-else-if="isRange(optionConfig.selectionType)">
              <range-filter
                v-if="!optionConfig.isShowSub"
                v-model="bindData.range"
                :min="maxMinOptions[0]"
                :max="maxMinOptions[1]"
              >
              </range-filter>
              <span v-else
                >已选出“{{ bindData.range.minNumber }}”到“{{
                  bindData.range.maxNumber
                }}”的单元格</span
              >
            </template>
            <span v-else v-html="optionConfig.name(selectionInfo)"></span>
          </span>
          <a-button
            v-if="!optionConfig.isShowSub"
            class="op-btn"
            type="primary"
            size="small"
            @click="openDetailPanel(optionConfig, index)"
            >确定</a-button
          >
        </div>
        <div v-if="optionConfig.isShowSub" class="detail-panel">
          <h6 class="op-sub-title">操作</h6>
          <div
            v-for="(item, i) in optionConfig.actions"
            :key="i"
            class="sub-item"
            :class="{
              active: value === item.value,
            }"
            @click="onCheckItemClicked(item)"
          >
            <span
              :ref="`viewIcon${item.value}`"
              class="view-icon sub-icon"
              style="transform: translateY(8px);"
              title="预览"
              @mouseleave="onMouseLeave()"
              @mouseenter="onMouseEnter($event, item.value)"
            >
              <img src="~@/assets/dataset/preview.png" alt="preview" />
            </span>
            <span class="check-item">
              <Status :value="value === item.value" />
              <span class="label fixed">{{ item.label }}</span>
            </span>
            <div
              :key="'input-' + i"
              class="replace-value-box"
              :class="{
                active: value === item.value,
              }"
            >
              <template v-if="i === 0">
                <a-input-number
                  v-if="isNumberColumn"
                  :key="'input-' + i"
                  v-model="bindData[item.bindKey]"
                  class="replace-value"
                  placeholder="Null"
                  size="small"
                  @change="onInput"
                ></a-input-number>
                <a-input
                  v-else
                  :key="'input-' + i"
                  v-model="bindData[item.bindKey]"
                  placeholder="Null"
                  class="replace-value"
                  size="small"
                  @input="onInput"
                ></a-input>
              </template>
            </div>
          </div>

          <div class="button-row">
            <a-button
              class="op-btn-sub"
              size="small"
              @click="cancel(optionConfig, index)"
              >取消</a-button
            >
            <a-button
              class="op-btn-sub"
              type="primary"
              size="small"
              @click="doOption"
              >确定</a-button
            >
          </div>
        </div>
      </div>
    </template>
  </div>
</template>
<script lang="ts">
import { isNumber, isArray } from 'lodash'
import KV from '@/components/form/kv'
import DataStore, {
  CellInfo,
  OptionPreViewAction,
} from '@/store/modules/dataview'
import { Component, Prop, Vue, Watch } from 'vue-property-decorator'
import Status from '../common/status.vue'
import CellSettingItem from '../common/cell-setting-item-interface'
import CompareFilter from '../common/compareFilter.vue'
import RangeFilter from '../common/rangeFilter.vue'
import OptionSettingCommon from '../common/vr-option-set-common'

@Component({
  components: {
    Status,
    RangeFilter,
    CompareFilter,
  },
})
export default class CellFilter extends Vue {
  /** 操作选项 */
  public get optionPreViewAction() {
    return OptionPreViewAction
  }
  /** 选中列是否为数值 */
  public get isNumberColumn() {
    const columnFind = DataStore.tableColumns.find((column) => {
      return (
        DataStore.tableSelectCells[0].columnName === column.name &&
        new Set(['decimal', 'int']).has(`${column.desc}`)
      )
    })
    return !!columnFind
  }

  /** 选项配置 */
  public optionSetting: Array<CellSettingItem> = [
    {
      showFunc(
        info: Array<CellInfo> | null,
        columnHasNullCell: boolean
      ): boolean {
        return columnHasNullCell
      },
      selectionType: OptionPreViewAction.cellFilterSelectNullCells,
      name(/* info: CellInfo|null */): string {
        return '选出该列存在缺失值的单元格'
      },
      actions: [
        {
          label: '为所选单元格重新赋值',
          value: OptionPreViewAction.cellFilterSelectNullCellsReset,
          bindKey: 'replaceValue',
        },
        {
          label: '删除所选单元格存在的行',
          value: OptionPreViewAction.cellFilterSelectNullCellsDeleteRows,
          bindKey: 'replaceValue',
        },
        {
          label: '仅保留所选单元格所在的行',
          value: OptionPreViewAction.cellFilterSelectNullCellsKeepRows,
          bindKey: '',
        },
      ],
      isShowSub: false,
    },
    {
      showFunc(info: Array<CellInfo> | null): boolean {
        const values = info
          ? info.map((item) => {
              return item.cellValue
            })
          : ''
        return info !== null && values != null
      },
      selectionType: OptionPreViewAction.cellFilterSelectContainsCell,
      name(info: Array<CellInfo> | null): string {
        let values = info
          ? info.map((item) => {
              return [null, '', undefined].includes(item.cellValue)
                ? 'NULL'
                : item.cellValue
            })
          : ''
        if (values) {
          values = [...new Set(values)]
        }
        values =
          values && isArray(values)
            ? (values as Array<string>).join(',')
            : 'NULL'
        return `选出该列值为<span class="values" title="${values}">"${values}"<span></span></span>的单元格`
      },
      actions: [
        {
          label: '为所选单元格重新赋值',
          value: OptionPreViewAction.cellFilterSelectContainsCellReset,
          bindKey: 'replaceValue',
        },
        {
          label: '删除所选单元格存在的行',
          value: OptionPreViewAction.cellFilterSelectContainsCellDeleteRows,
          bindKey: 'replaceValue',
        },
        {
          label: '仅保留所选单元格所在的行',
          value: OptionPreViewAction.cellFilterSelectContainsCellKeepRows,
          bindKey: '',
        },
      ],
      isShowSub: false,
    },
    {
      showFunc(
        info: Array<CellInfo> | null,
        columnHasNullCell: boolean,
        isNumberCell: boolean,
        maxMinOptions: Array<number | null>,
        selectionType: OptionPreViewAction
      ): boolean {
        return (
          isNumberCell &&
          maxMinOptions[0] !== null &&
          maxMinOptions[1] !== null &&
          selectionType === OptionPreViewAction.cellFilterSelectCompareCell
        )
      },
      selectionType: OptionPreViewAction.cellFilterSelectCompareCell,
      name(/* info: CellInfo|null */): string {
        return 'gtlt-filter'
      },
      actions: [
        {
          label: '为所选单元格重新赋值',
          value: OptionPreViewAction.cellFilterSelectCompareCellReset,
          bindKey: 'replaceValue',
        },
        {
          label: '删除所选单元格存在的行',
          value: OptionPreViewAction.cellFilterSelectCompareCellDeleteRows,
          bindKey: 'replaceValue',
        },
        {
          label: '仅保留所选单元格所在的行',
          value: OptionPreViewAction.cellFilterSelectCompareCellKeepRows,
          bindKey: '',
        },
      ],
      isShowSub: false,
    },
    {
      showFunc(
        info: Array<CellInfo> | null,
        columnHasNullCell: boolean,
        isNumberCell: boolean,
        maxMinOptions: Array<number | null>,
        selectionType: OptionPreViewAction
      ): boolean {
        return (
          isNumberCell &&
          maxMinOptions[0] !== null &&
          maxMinOptions[1] !== null &&
          selectionType === OptionPreViewAction.cellFilterSelectRangeCell
        )
      },
      selectionType: OptionPreViewAction.cellFilterSelectRangeCell,
      name(/* info: CellInfo|null */): string {
        return 'range-filter'
      },
      actions: [
        {
          label: '为所选单元格重新赋值',
          value: OptionPreViewAction.cellFilterSelectRangeCellReset,
          bindKey: 'replaceValue',
        },
        {
          label: '删除所选单元格存在的行',
          value: OptionPreViewAction.cellFilterSelectRangeCellDeleteRows,
          bindKey: 'replaceValue',
        },
        {
          label: '仅保留所选单元格所在的行',
          value: OptionPreViewAction.cellFilterSelectRangeCellKeepRows,
          bindKey: '',
        },
      ],
      isShowSub: false,
    },
  ]
  /** 当前单元格所在的列中是否有null */
  @Prop({
    type: Boolean,
    default() {
      return false
    },
  })
  columnHasNullCell!: boolean

  /** 是否为数值型单元格 */
  @Prop({
    type: Boolean,
    default() {
      return false
    },
  })
  isNumberCell!: boolean

  /** 列中最大值与最小值 */
  @Prop({
    type: Array,
    default() {
      return [null, null]
    },
  })
  maxMinOptions!: Array<number>

  /** 列中选中单元格的最大值与最小值 */
  @Prop({
    type: Array,
    default() {
      return [null, null]
    },
  })
  maxMinOptionsSelect!: [number | null, number | null]

  /** 监听最大值、最小值用于动态配置数值范围等参数 */
  @Watch('maxMinOptionsSelect', {
    immediate: true,
    deep: true,
  })
  getMaxMinOptionsSelect(newValue: [number | null, number | null]) {
    if (isNumber(newValue[0]) && isNumber(newValue[1])) {
      this.$set(this.bindData, 'compare', {
        compareMode: '=',
        delimiter:
          isNumber(newValue[0]) && ![Infinity, -Infinity].includes(newValue[0])
            ? newValue[0]
            : this.maxMinOptions[0],
      })
      DataStore.setVrCompareInfo({
        compareMode: '=',
        delimiter:
          isNumber(newValue[0]) && ![Infinity, -Infinity].includes(newValue[0])
            ? newValue[0]
            : this.maxMinOptions[0],
      })
      if (this.isMutipleSelectMode) {
        this.$set(this.bindData, 'range', {
          minNumber:
            isNumber(newValue[0]) &&
            ![Infinity, -Infinity].includes(newValue[0])
              ? newValue[0]
              : this.maxMinOptions[0],
          maxNumber:
            isNumber(newValue[1]) &&
            ![Infinity, -Infinity].includes(newValue[1])
              ? newValue[1]
              : this.maxMinOptions[1],
        })
        DataStore.setVrRangeInfo([newValue[0], newValue[1]])
      }
    }
  }

  /** 获取重置标识 */
  get vrResetTag() {
    return DataStore.vrResetTag
  }

  /** 监听重置标识，并重置相关参数 */
  @Watch('vrResetTag')
  getResetTag() {
    this.optionSetting.forEach((item) => {
      item.isShowSub = false
    })
    if (DataStore.vrCurrenSetMode !== null) {
      DataStore.setTableVrCurrenSetMode(null)
    }
  }

  /** 监听最大值，最小值并实时设置组件状态 */
  @Watch('maxMinOptions', {
    immediate: true,
    deep: true,
  })
  getMaxMinOptions(newValue: [number | null, number | null]) {
    if (isNumber(newValue[0]) && isNumber(newValue[1])) {
      const delimiter =
        isNumber(this.maxMinOptionsSelect[0]) &&
        ![Infinity, -Infinity].includes(this.maxMinOptionsSelect[0])
          ? this.maxMinOptionsSelect[0]
          : this.maxMinOptions[0]
      this.$set(this.bindData, 'compare', {
        compareMode: '=',
        delimiter,
      })
      DataStore.setVrCompareInfo({
        compareMode: '=',
        delimiter,
      })
      if (!this.isMutipleSelectMode) {
        this.$set(this.bindData, 'range', {
          minNumber: newValue[0],
          maxNumber: newValue[1],
        })
        DataStore.setVrRangeInfo([newValue[0], newValue[1]])
      }
    }
  }

  /** 操作标识绑定值 */
  value: string = OptionPreViewAction.cellFilterSelectNullCellsReset

  /** 是否展示操作详情 */
  isShowSub: boolean = false

  /**
   * 多选模式通过已选值填入默认，单选模式用数据表查询的最大值，最小值设为默认值
   */
  get isMutipleSelectMode(): boolean {
    return this.isNumberCell && DataStore.tableSelectCells.length > 1
  }

  /** 获取选中的数据 */
  get selectValues(): Array<number> {
    let result: Array<number> = []
    if (this.isNumberCell) {
      result = DataStore.tableSelectCells.reduce((rec: Array<number>, item) => {
        if (isNumber(item.cellValue)) {
          rec.push(item.cellValue)
        }
        return rec
      }, [])
    }
    return result
  }

  /** 操作绑定的数据 */
  bindData: KV = {
    replaceValue: 'Null',
    compare: {
      compareMode: '>',
      delimiter: 0,
    },
    range: {
      minNumber: 0,
      maxNumber: 0,
    },
  }

  /**
   * 重置数据绑定信息
   */
  resetDataBind() {
    this.$set(this.bindData, 'replaceValue', '')
  }

  /**
   * 选中信息
   */
  get selectionInfo() {
    return DataStore.tableSelectCells.length > 0
      ? DataStore.tableSelectCells
      : null
  }

  mounted() {
    DataStore.setColumnFilterSelectNullCellsResetValue(
      this.bindData.replaceValue
    )
  }

  /** 操作点击展开详情 */
  openDetailPanel(optionConfig: CellSettingItem, index: number) {
    optionConfig.isShowSub = true
    this.optionSetting.forEach((item, i) => {
      item.isShowSub = index === i
    })
    if (optionConfig.actions.length > 0) {
      this.value = optionConfig.actions[0].value
    }
    this.resetDataBind()
    switch (optionConfig.selectionType) {
      case OptionPreViewAction.cellFilterSelectContainsCell:
        OptionSettingCommon.setCellFilterSelectContainsCell(
          optionConfig.selectionType
        )
        this.$message.info(
          `已选出该列中值包含 ${[
            ...new Set(
              this.selectionInfo
                ? this.selectionInfo.map((item) => item.cellValue)
                : 'Null'
            ),
          ].join(',')} 的单元格`
        )
        break
      case OptionPreViewAction.cellFilterSelectNullCells:
        OptionSettingCommon.setCellFilterSelectNullCells(
          optionConfig.selectionType
        )
        this.$message.info('已选出该列中包含缺失值的单元格')
        break
      case OptionPreViewAction.cellFilterSelectCompareCell:
        OptionSettingCommon.setCellFilterSelectCompareCell(
          optionConfig.selectionType
        )
        this.$message.info(
          `已选出该列中值 ${this.bindData.compare.compareMode} ${this.bindData.compare.delimiter} 的单元格`
        )
        break
      case OptionPreViewAction.cellFilterSelectRangeCell:
        OptionSettingCommon.setCellFilterSelectRangeCell(
          optionConfig.selectionType
        )
        this.$message.info(
          `已选出该列中值在 ${this.bindData.range.minNumber} - ${this.bindData.range.maxNumber} 范围的单元格`
        )
        break
      default:
        break
    }
  }
  /** 是否为比较模式 */
  isGTLT(mode: OptionPreViewAction) {
    return mode === OptionPreViewAction.cellFilterSelectCompareCell
  }
  /** 是否为范围模式 */
  isRange(mode: OptionPreViewAction) {
    return mode === OptionPreViewAction.cellFilterSelectRangeCell
  }
  /** 执行操作 */
  doOption() {
    switch (this.value) {
      case OptionPreViewAction.cellFilterSelectNullCellsReset:
        this.$emit('actiondone', {
          action: this.value,
          desc:
            '单元格，筛选面板 > 选出该列存在缺失值的单元格 > 为所选单元格重新赋值',
          data: {
            replaceValue: this.bindData.replaceValue,
          },
        })
        break

      case OptionPreViewAction.cellFilterSelectNullCellsDeleteRows:
        this.$emit('actiondone', {
          action: this.value,
          desc:
            '列操作，筛选面板 > 选出该列存在缺失值的单元格 > 删除所选单元格存在的行',
        })
        break

      case OptionPreViewAction.cellFilterSelectNullCellsKeepRows:
        this.$emit('actiondone', {
          action: this.value,
          desc:
            '列操作，筛选面板 > 选出该列存在缺失值的单元格 > 仅保留所选单元格所在的行',
        })
        break

      case OptionPreViewAction.cellFilterSelectContainsCellReset:
        this.$emit('actiondone', {
          action: this.value,
          replaceValue: this.bindData.replaceValue,
          desc:
            '单元格，筛选面板 > 选出与选中单元格值相等的单元格 > 为所选单元格重新赋值',
        })
        break

      case OptionPreViewAction.cellFilterSelectContainsCellKeepRows:
        this.$emit('actiondone', {
          action: this.value,
          desc:
            '单元格，筛选面板 > 选出与选中单元格值相等的单元格 > 仅保留所选单元格存在的行',
        })
        break

      case OptionPreViewAction.cellFilterSelectContainsCellDeleteRows:
        this.$emit('actiondone', {
          action: this.value,
          desc:
            '单元格，筛选面板 > 选出与选中单元格值相等的单元格 > 删除所选单元格存在的行',
        })
        break
      case OptionPreViewAction.cellFilterSelectCompareCellReset:
        this.$emit('actiondone', {
          action: this.value,
          replaceValue: this.bindData.replaceValue,
          desc:
            '单元格，筛选面板 > 选出与选中单元格值相等的单元格 > 为所选单元格重新赋值',
        })
        break
      case OptionPreViewAction.cellFilterSelectCompareCellDeleteRows:
        this.$emit('actiondone', {
          action: this.value,
          desc:
            '单元格，筛选面板 > 选出与选中单元格值相等的单元格 > 删除单元格所在的行',
        })
        break
      case OptionPreViewAction.cellFilterSelectCompareCellKeepRows:
        this.$emit('actiondone', {
          action: this.value,
          desc:
            '单元格，筛选面板 > 选出与选中单元格值相等的单元格 > 仅保留单元格所在的行',
        })
        break
      case OptionPreViewAction.cellFilterSelectRangeCellReset:
        this.$emit('actiondone', {
          action: this.value,
          replaceValue: this.bindData.replaceValue,
          desc:
            '单元格，筛选面板 > 选出与选中单元格值相等的单元格 > 为所选单元格重新赋值',
        })
        break
      case OptionPreViewAction.cellFilterSelectRangeCellDeleteRows:
        this.$emit('actiondone', {
          action: this.value,
          desc:
            '单元格，筛选面板 > 选出与选中单元格值相等的单元格 > 删除单元格所在的行',
        })
        break
      case OptionPreViewAction.cellFilterSelectRangeCellKeepRows:
        this.$emit('actiondone', {
          action: this.value,
          desc:
            '单元格，筛选面板 > 选出与选中单元格值相等的单元格 > 仅保留单元格所在的行',
        })
        break
      default:
        break
    }
  }

  /** 点击操作回调 */
  onCheckItemClicked(item: any) {
    this.value = item.value
  }
  /** 输入或change事件回调 */
  onInput() {
    DataStore.setColumnFilterSelectNullCellsResetValue(
      this.bindData.replaceValue
    )
  }

  /** 取消 */
  cancel(optionConfig: CellSettingItem) {
    this.bindData.replaceValue = ''
    optionConfig.isShowSub = false
    this.onInput()
    DataStore.setTableVrCurrenSetMode(null)
  }

  /** 预览鼠标移入事件 */
  onMouseEnter(event: any, action: string) {
    const target = event.target as HTMLElement
    if (target) {
      DataStore.setPreviewAction(action)
      DataStore.setHoverYPos(target.getBoundingClientRect().top - 16)
    }
  }

  /** 预览鼠标移出事件 */
  onMouseLeave() {
    DataStore.setHoverYPos(-1)
  }
}
</script>
<style lang="less" scoped>
@import url('../op.less');
</style>
